/**
 * copyright (C) geolabs 2006-2007
 * author: Gérald Fenoy
 */

/**
 * The Xml class
 *
 */
OctoXml=Class.create({

  dumpAsJson: function(obj){
      
      var tmp="";
      
      if(obj && obj instanceof Array){
	tmp="[ ";
	for(var i=0;i<obj.length;i++){
	  var obji=obj[i];
	  tmp+=this.dumpAsJson(obji)+", \n";
	}
	tmp=tmp.substr(0,tmp.length-3);
	tmp+="]";
      }
      else 
	if((typeof obj)=="object"){
	  tmp="{ ";
	  var hasNode=false;
	  for(var i in obj){
	    var obji=obj[i];
	    tmp+="\""+i+"\": "+this.dumpAsJson(obji)+", ";
	    hasNode=true;
	  }
	  if(!hasNode){tmp="null";}
	  else{
	    tmp=tmp.substr(0,tmp.length-2);
	    tmp+=" }";
	  }
	}
	else
	  tmp="\""+obj+"\"";

      return tmp;

    },

  jsonFromElement: function(element,isRoot){

      var tree={};      

      tree[element.tagName]={};
      
      var i=0;
      var hasAttribute=0;
      if(element.attributes)
	for(i=0;i<element.attributes.length;i++){
	  tree[element.tagName]["@"+element.attributes[i].nodeName]=(element.attributes[i].nodeValue||"");
	  hasAttribute++;
	}

      if(element.childNodes.length>0){
	for(i=0;i<element.childNodes.length;i++){
	  var tmp=element.childNodes[i];

	  if(!tree[element.tagName][tmp.tagName]){
	    
	    if(tmp.nodeName!="#text" && tmp.nodeName!="#cdata-section"){
	      tree[element.tagName][tmp.tagName]=this.jsonFromElement(tmp,-1);
	    }
	    else{
	      if(!hasAttribute){
		if(i+1>=element.childNodes.length){
		  if(tmp.nodeName!="#text"){
		    tree[element.tagName]={};
		    tree[element.tagName]["#cdata"]=tmp.nodeValue;
		  }
		  else
		    tree[element.tagName]=tmp.nodeValue;
		}
		else{
		  if(tmp.nodeValue.search(/[^ \f\n\r\t\v]/)>=0){
		    if(!tree[element.tagName][tmp.nodeName])
		      tree[element.tagName][tmp.nodeName]=tmp.nodeValue;
		    else{
		      if(!tree[element.tagName][tmp.nodeName] instanceof Array){
			var swap=tree[element.tagName][tmp.nodeName];
			tree[element.tagName][tmp.nodeName]=new Array();
			tree[element.tagName][tmp.nodeName][0]=swap;
		      }
		      tree[element.tagName][tmp.nodeName][tree[element.tagName][tmp.nodeName].length]=tmp.nodeValue;			
		    }
		  }
		  
		  for(var j=i+1;j<element.childNodes.length;j++){
		    
		    if(element.childNodes[j].tagName){
		      if(!tree[element.tagName][element.childNodes[j].tagName]){
			tree[element.tagName][element.childNodes[j].tagName]=this.jsonFromElement(element.childNodes[j],1);
		      }
		      else{
			if(!(tree[element.tagName][element.childNodes[j].tagName] instanceof Array)){
			  var swap=tree[element.tagName][element.childNodes[j].tagName];
			  tree[element.tagName][element.childNodes[j].tagName]=new Array();
			  tree[element.tagName][element.childNodes[j].tagName][0]=swap;
			  }
			tree[element.tagName][element.childNodes[j].tagName][tree[element.tagName][element.childNodes[j].tagName].length]=this.jsonFromElement(element.childNodes[j],1);
		      }
		      
		    }
		    else
		      if(element.childNodes[j].nodeValue.search(/[^ \f\n\r\t\v]/)>=0){
			var currNodeName=(element.childNodes[j].nodeName=="#text")?element.childNodes[j].nodeName:"#cdata";
			if(!tree[element.tagName][currNodeName])
			  tree[element.tagName][currNodeName]=element.childNodes[j].nodeValue;
			else{
			  if(!(tree[element.tagName][currNodeName] instanceof Array)){
			    var swap=tree[element.tagName][currNodeName];
			    tree[element.tagName][currNodeName]=new Array();
			    tree[element.tagName][currNodeName][0]=swap;
			  }			  
			  tree[element.tagName][currNodeName][tree[element.tagName][currNodeName].length]=element.childNodes[j].nodeValue;
			}
		      }
		  }
		  
		  break;
		}
	      }
	      else{
		if(tmp.nodeValue.search(/[^ \f\n\r\t\v]/)>=0)
		  tree[element.tagName][tmp.nodeName]=tmp.nodeValue;
	      }
	      
	    }
	    
	  }
	  else{
	    if(!(tree[element.tagName][tmp.tagName] instanceof Array)){
	      var swap=tree[element.tagName][tmp.tagName];
	      tree[element.tagName][tmp.tagName]=new Array();
	      tree[element.tagName][tmp.tagName][0]=swap;
	    }
	    
	    if(tmp.nodeName!="#text"){
	      tree[element.tagName][tmp.tagName][tree[element.tagName][tmp.tagName].length]=this.jsonFromElement(tmp,-1);
	    }
	    else{
	      if(!hasAttribute){
		tree[element.tagName]=(tmp.nodeName=="#text")?tmp.nodeValue:"#cdata";
	      }
	      else{
		tree[element.tagName][tmp.nodeName]=tmp.nodeValue;
	      }
	    }
	    
	  }
	  
	}
      }
      else{
	if(!hasAttribute){
	  if(element.tagName){
	    tree[element.tagName]=element.nodeValue;
	  }
	  else{
	    return element.nodeValue;
	  }
	}
      }
      
      if(isRoot){
	for(var i in tree){
	  if(tree[i]){
	    //if(typeof tree!="object")
	    if(((typeof tree[i]=="string") && tree[i].search(/[^ \f\n\r\t\v]/)>=0)
	       || (typeof tree[i]=="object"))
	      return tree[i];
	    else{
	      return null;
	    }
	  }
	  else
	    return null;
	}
      }

      return tree;

    },

  getDocument: function(){
      try{
	var tmp = new ActiveXObject('Microsoft.XMLDOM');
	return tmp;
      }catch(e){
	return document;
      }
    },

  setAttribute: function(element,name,value){
	try{ element.setAttribute(name,value); }
	catch(e){ element.attributes[name]=value; }
    },

  addAttributes: function(){
      for(var i in arguments[1]){
	var test=i+"";
	if(test.charAt(0)=="O")
	  this.setAttribute(arguments[0],test.substr(1,test.length),arguments[1][test]);
	else this.setAttribute(arguments[0],i,arguments[1][i]);
      }
    },

  serializeToString: function(){
      var result=null;
      try{
	result=(new XMLSerializer()).serializeToString(arguments[0]);
      }catch(e){
	result=arguments[0].xml;
      }
      return result;
    },

  parseFromString: function(){
      var result=null;
      try{result=(new DOMParser()).parseFromString(arguments[0], "text/xml");}
      catch(e){
	var doc=new ActiveXObject("Microsoft.XMLDOM");
	doc.async="false";
	doc.loadXML(arguments[0]);
	result=doc.childNodes[0];
      }
      if(result.childNodes[0].tagName=="parsererror"){
	throw("_debug : OctoXml was unable to parse xml from string :\n"+this.serializeToString(result.childNodes[0]));
      }
      return result;
    },

  createElement: function(tagName,attributes){
      var newElement;
      
      try{
	xmldoc = new ActiveXObject('Microsoft.XMLDOM');
	
	var newElementBis=xmldoc.createElement(tagName);
	
	this.addAttributes(newElementBis,attributes);
	
	xmldoc.appendChild(newElementBis);
	
	newElement=xmldoc.childNodes[0];
	
      }
      catch(e){
	
	newElement=document.createElement(tagName);
	
	this.addAttributes(newElement,attributes);
	
      }
      return newElement;
    },

  getElementsByAttr: function(xml,attr){
      var result=new Array();
      var countElements=0;
      for(var i=0;i<xml.childNodes.length;i++){
	
	if(xml.childNodes[i].nodeName!="#text" &&
	   xml.childNodes[i].nodeName!="#cdata"){
	  
	  for(var j=0;j<xml.childNodes[i].attributes.length;j++){
	    if(xml.childNodes[i].attributes[j].nodeName==attr){
	      result[countElements]=xml.childNodes[i];
	      countElements++;
	    }
	  }
	  
	  if(xml.childNodes[i].childNodes){
	    var tmp=this.getElementsByAttr(xml.childNodes[i],attr);
	    for(var k=0;k<tmp.length;k++){
	      result[countElements]=tmp[k];
	      countElements++;
	    }
	  }
	  
	}

      }

      return result;
    }

  });

